//
//  UIView+Additions.m
//  DJAppModule
//
//  Created by Lynn_Lin on 2018/5/8.
//

#import "UIView+Additions.h"

@implementation UIView (Additions)

- (UIImage *) screenshot {
    UIGraphicsBeginImageContext(self.bounds.size);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    NSData *imageData = UIImageJPEGRepresentation(image, 0.75);
    image = [UIImage imageWithData:imageData];
    return image;
}

- (nullable UIImage *)dj_snapshotImage {
    if (CGRectEqualToRect(self.bounds, CGRectZero)) return nil;
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *snap = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snap;
}

- (nullable NSData *)dj_snapshotData {
    UIImage *image = [self dj_snapshotImage];
    NSData *imageData =UIImageJPEGRepresentation(image, 0.75);
    return imageData;
}

- (nullable UIImage *)dj_snapshotImageAfterScreenUpdates:(BOOL)afterUpdates {
    if (CGRectEqualToRect(self.bounds, CGRectZero)) return nil;
    if (![self respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
        return [self dj_snapshotImage];
    }
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, 0);
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:afterUpdates];
    UIImage *snap = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snap;
}

- (nullable NSData *)dj_snapshotDataAfterScreenUpdates:(BOOL)afterUpdates {
    UIImage *image = [self dj_snapshotImageAfterScreenUpdates:afterUpdates];
    NSData *imageData =UIImageJPEGRepresentation(image, 0.75);
    return imageData;
}

- (void)dj_setViewMaskWithRadius:(CGFloat)radius byRoundingCorners:(UIRectCorner)corners{
    UIBezierPath *rounded = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *shape = [[CAShapeLayer alloc] init];
    [shape setPath:rounded.CGPath];
    self.layer.mask = shape;
}

- (void)dj_setLayerShadow:(UIColor *)color offset:(CGSize)offset radius:(CGFloat)radius {
    self.layer.shadowColor = color.CGColor;
    self.layer.shadowOffset = offset;
    self.layer.shadowRadius = radius;
    self.layer.shadowOpacity = 1;
    self.layer.shouldRasterize = YES;
    self.layer.rasterizationScale = [UIScreen mainScreen].scale;
}

- (CGPoint)dj_convertPoint:(CGPoint)point toViewOrWindow:(nullable UIView *)view {
    
    if (!view) {
        if ([self isKindOfClass:[UIWindow class]]) {
            return [((UIWindow *)self) convertPoint:point toWindow:nil];
        } else {
            return [self convertPoint:point toView:nil];
        }
    }
    
    UIWindow *from = [self isKindOfClass:[UIWindow class]] ? (id)self : self.window;
    UIWindow *to = [view isKindOfClass:[UIWindow class]] ? (id)view : view.window;
    if ((!from || !to) || (from == to)) return [self convertPoint:point toView:view];
    point = [self convertPoint:point toView:from];
    point = [to convertPoint:point fromWindow:from];
    point = [view convertPoint:point fromView:to];
    return point;
}

- (CGPoint)dj_convertPoint:(CGPoint)point fromViewOrWindow:(nullable UIView *)view {
    if (!view) {
        if ([self isKindOfClass:[UIWindow class]]) {
            return [((UIWindow *)self) convertPoint:point fromWindow:nil];
        } else {
            return [self convertPoint:point fromView:nil];
        }
    }
    
    UIWindow *from = [view isKindOfClass:[UIWindow class]] ? (id)view : view.window;
    UIWindow *to = [self isKindOfClass:[UIWindow class]] ? (id)self : self.window;
    if ((!from || !to) || (from == to)) return [self convertPoint:point fromView:view];
    point = [from convertPoint:point fromView:view];
    point = [to convertPoint:point fromWindow:from];
    point = [self convertPoint:point fromView:to];
    return point;
}

- (CGRect)dj_convertRect:(CGRect)rect toViewOrWindow:(nullable UIView *)view {
    if (!view) {
        if ([self isKindOfClass:[UIWindow class]]) {
            return [((UIWindow *)self) convertRect:rect toWindow:nil];
        } else {
            return [self convertRect:rect toView:nil];
        }
    }
    
    UIWindow *from = [self isKindOfClass:[UIWindow class]] ? (id)self : self.window;
    UIWindow *to = [view isKindOfClass:[UIWindow class]] ? (id)view : view.window;
    if (!from || !to) return [self convertRect:rect toView:view];
    if (from == to) return [self convertRect:rect toView:view];
    rect = [self convertRect:rect toView:from];
    rect = [to convertRect:rect fromWindow:from];
    rect = [view convertRect:rect fromView:to];
    return rect;
}

- (CGRect)dj_convertRect:(CGRect)rect fromViewOrWindow:(nullable UIView *)view {
    if (!view) {
        if ([self isKindOfClass:[UIWindow class]]) {
            return [((UIWindow *)self) convertRect:rect fromWindow:nil];
        } else {
            return [self convertRect:rect fromView:nil];
        }
    }
    
    UIWindow *from = [view isKindOfClass:[UIWindow class]] ? (id)view : view.window;
    UIWindow *to = [self isKindOfClass:[UIWindow class]] ? (id)self : self.window;
    if ((!from || !to) || (from == to)) return [self convertRect:rect fromView:view];
    rect = [from convertRect:rect fromView:view];
    rect = [to convertRect:rect fromWindow:from];
    rect = [self convertRect:rect fromView:to];
    return rect;
}

- (UIView*)descendantOrSelfWithClass:(Class)cls {
    if ([self isKindOfClass:cls])
        return self;
    
    for (UIView* child in self.subviews) {
        UIView* it = [child descendantOrSelfWithClass:cls];
        if (it)
            return it;
    }
    
    return nil;
}

- (UIView*)ancestorOrSelfWithClass:(Class)cls {
    if ([self isKindOfClass:cls]) {
        return self;
    } else if (self.superview) {
        return [self.superview ancestorOrSelfWithClass:cls];
    } else {
        return nil;
    }
}

- (void)removeAllSubviews {
    while (self.subviews.count) {
        UIView* child = self.subviews.lastObject;
        [child removeFromSuperview];
    }
}
- (void)dismissAsKeyboardAnimationDidStop {
    [self removeFromSuperview];
}


- (UIViewController*)viewController {
    for (UIView* next = [self superview]; next; next = next.superview) {
        UIResponder* nextResponder = [next nextResponder];
        if ([nextResponder isKindOfClass:[UIViewController class]]) {
            return (UIViewController*)nextResponder;
        }
    }
    return nil;
}


-(void)removeAllSubViews{
    
    for( UIView *v in [self subviews]){
        [v removeFromSuperview];
    }
}




CGPoint demoLGStart(CGRect bounds){
    return CGPointMake(bounds.origin.x, bounds.origin.y + bounds.size.height * 0.25);
}
CGPoint demoLGEnd(CGRect bounds){
    return CGPointMake(bounds.origin.x, bounds.origin.y + bounds.size.height * 0.75);
}
CGPoint demoRGCenter(CGRect bounds){
    return CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
}
CGFloat demoRGInnerRadius(CGRect bounds){
    CGFloat r = bounds.size.width < bounds.size.height ? bounds.size.width : bounds.size.height;
    return r * 0.125;
}


+ (void) drawGradientInRect:(CGRect)rect withColors:(NSArray*)colors{
    
    NSMutableArray *ar = [NSMutableArray array];
    for(UIColor *c in colors){
        [ar addObject:(id)c.CGColor];
    }
    
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    
    
    
    CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]);
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)ar, NULL);
    
    
    CGContextClipToRect(context, rect);
    
    CGPoint start = CGPointMake(0.0, 0.0);
    CGPoint end = CGPointMake(0.0, rect.size.height);
    
    CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
    
    CGGradientRelease(gradient);
    CGContextRestoreGState(context);
    
}


+ (void) drawLinearGradientInRect:(CGRect)rect colors:(CGFloat[])colours{
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    CGContextSaveGState(context);
    
    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colours, NULL, 2);
    CGColorSpaceRelease(rgb);
    CGPoint start, end;
    
    start = demoLGStart(rect);
    end = demoLGEnd(rect);
    
    
    
    CGContextClipToRect(context, rect);
    CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
    
    CGGradientRelease(gradient);
    
    CGContextRestoreGState(context);
    
}



+ (void) drawRoundRectangleInRect:(CGRect)rect withRadius:(CGFloat)radius{
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    
    CGRect rrect = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height );
    
    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect);
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect);
    CGContextMoveToPoint(context, minx, midy);
    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
    CGContextClosePath(context);
    CGContextDrawPath(context, kCGPathFill);
}




+ (void) drawLineInRect:(CGRect)rect colors:(CGFloat[])colors {
    
    [UIView drawLineInRect:rect colors:colors width:1 cap:kCGLineCapButt];
    
}
+ (void) drawLineInRect:(CGRect)rect red:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha{
    CGFloat colors[4];
    colors[0] = red;
    colors[1] = green;
    colors[2] = blue;
    colors[3] = alpha;
    [UIView drawLineInRect:rect colors:colors];
}


+ (void) drawLineInRect:(CGRect)rect colors:(CGFloat[])colors width:(CGFloat)lineWidth cap:(CGLineCap)cap{
    
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    
    
    CGContextSetRGBStrokeColor(context, colors[0], colors[1], colors[2], colors[3]);
    CGContextSetLineCap(context,cap);
    CGContextSetLineWidth(context, lineWidth);
    
    CGContextMoveToPoint(context, rect.origin.x, rect.origin.y);
    CGContextAddLineToPoint(context,rect.origin.x+rect.size.width, rect.origin.y+rect.size.height);
    CGContextStrokePath(context);
    
    
    CGContextRestoreGState(context);
    
}


+ (void)drawRect:(CGRect)rect fill:(const CGFloat*)fillColors radius:(CGFloat)radius {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    
    if (fillColors) {
        CGContextSaveGState(context);
        CGContextSetFillColor(context, fillColors);
        if (radius) {
            UIBezierPath* path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
            CGContextAddPath(context, path.CGPath);
            CGContextFillPath(context);
        } else {
            CGContextFillRect(context, rect);
        }
        CGContextRestoreGState(context);
    }
    
    CGColorSpaceRelease(space);
}

+ (void)drawRect:(CGRect)rect fillColor:(UIColor *)fillColor radius:(CGFloat)radius {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    
    if (fillColor) {
        CGContextSaveGState(context);
        const CGFloat* components = CGColorGetComponents(fillColor.CGColor);
        CGContextSetRGBFillColor(context, components[0], components[1], components[2], components[3]);
        if (radius) {
            UIBezierPath* path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
            CGContextAddPath(context, path.CGPath);
            CGContextFillPath(context);
        } else {
            CGContextFillRect(context, rect);
        }
        CGContextRestoreGState(context);
    }
    
    CGColorSpaceRelease(space);
}

+ (void)strokeLines:(CGRect)rect stroke:(const CGFloat*)strokeColor {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    
    CGContextSaveGState(context);
    CGContextSetStrokeColorSpace(context, space);
    CGContextSetStrokeColor(context, strokeColor);
    CGContextSetLineWidth(context, 1.0);
    
    {
        CGPoint points[] = {{rect.origin.x+0.5, rect.origin.y-0.5},
            {rect.origin.x+rect.size.width, rect.origin.y-0.5}};
        CGContextStrokeLineSegments(context, points, 2);
    }
    {
        CGPoint points[] = {{rect.origin.x+0.5, rect.origin.y+rect.size.height-0.5},
            {rect.origin.x+rect.size.width-0.5, rect.origin.y+rect.size.height-0.5}};
        CGContextStrokeLineSegments(context, points, 2);
    }
    {
        CGPoint points[] = {{rect.origin.x+rect.size.width-0.5, rect.origin.y},
            {rect.origin.x+rect.size.width-0.5, rect.origin.y+rect.size.height}};
        CGContextStrokeLineSegments(context, points, 2);
    }
    {
        CGPoint points[] = {{rect.origin.x+0.5, rect.origin.y},
            {rect.origin.x+0.5, rect.origin.y+rect.size.height}};
        CGContextStrokeLineSegments(context, points, 2);
    }
    
    CGContextRestoreGState(context);
    
    CGColorSpaceRelease(space);
}

#pragma mark - UIView frame相关

- (CGFloat)dj_left{
    return self.frame.origin.x;
}

- (void)setDj_left:(CGFloat)dj_left {
    CGRect frame = self.frame;
    frame.origin.x = dj_left;
    self.frame = frame;
}

- (CGFloat)dj_top {
    return self.frame.origin.y;
}

- (void)setDj_top:(CGFloat)dj_top {
    CGRect frame = self.frame;
    frame.origin.y = dj_top;
    self.frame = frame;
}

- (CGFloat)dj_right {
    return self.frame.origin.x + self.frame.size.width;
}

- (void)setDj_right:(CGFloat)dj_right {
    CGRect frame = self.frame;
    frame.origin.x = dj_right - frame.size.width;
    self.frame = frame;
}

- (CGFloat)dj_bottom {
    return self.frame.origin.y + self.frame.size.height;
}

- (void)setDj_bottom:(CGFloat)dj_bottom {
    CGRect frame = self.frame;
    frame.origin.y = dj_bottom - frame.size.height;
    self.frame = frame;
}

- (CGFloat)dj_width {
    return self.frame.size.width;
}

- (void)setDj_width:(CGFloat)dj_width {
    CGRect frame = self.frame;
    frame.size.width = dj_width;
    self.frame = frame;
}

- (CGFloat)dj_height {
    return self.frame.size.height;
}

- (void)setDj_height:(CGFloat)dj_height {
    CGRect frame = self.frame;
    frame.size.height = dj_height;
    self.frame = frame;
}

- (CGFloat)dj_centerX {
    return self.center.x;
}

- (void)setDj_centerX:(CGFloat)dj_centerX {
    self.center = CGPointMake(dj_centerX, self.center.y);
}

- (CGFloat)dj_centerY {
    return self.center.y;
}

-(void)setDj_centerY:(CGFloat)dj_centerY {
    self.center = CGPointMake(self.center.x, dj_centerY);
}

- (CGPoint)dj_origin {
    return self.frame.origin;
}

- (void)setDj_origin:(CGPoint)dj_origin {
    CGRect frame = self.frame;
    frame.origin = dj_origin;
    self.frame = frame;
}

-(CGSize)dj_size {
    return self.frame.size;
}
- (void)setDj_size:(CGSize)dj_size {
    CGRect frame = self.frame;
    frame.size = dj_size;
    self.frame = frame;
}

- (CGFloat)dj_originY{
    return self.frame.origin.y;
}

- (void)setDj_originY:(CGFloat)dj_originY {
    CGRect frame = self.frame;
    frame.origin.y = dj_originY;
    self.frame = frame;
}

- (CGFloat)dj_originX {
    return self.frame.origin.x;
}

- (void)setDj_originX:(CGFloat)dj_originX {
    CGRect frame = self.frame;
    frame.origin.x = dj_originX;
    self.frame = frame;
    
}

- (CGFloat)dj_boundsY {
    return self.bounds.origin.y;
}

- (void)setDj_boundsY:(CGFloat)dj_boundsY {
    CGRect bounds = self.bounds;
    bounds.origin.y = dj_boundsY;
    self.bounds = bounds;
}

@end
